package game.gui;

import game.driver.Controller;
import game.utils.Util;
import game.player.AIPlayer;
import game.model.Card;

import java.awt.BorderLayout;
import java.awt.Point;
import java.io.File;
import java.io.IOException;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.table.*;

import java.awt.*;
import java.awt.event.*;

import javax.swing.*;
import javax.swing.event.TableModelListener;

import java.awt.Container;
import java.awt.Insets;
import java.awt.Dimension;
import java.awt.LayoutManager;

import java.util.Timer;
import java.util.TimerTask;

/**
 * Creates the GUI. Andrea created the board and added buttons to it. Kristen
 * created all menus and added them to the board.
 * 
 * @author Andrea and Kristen
 */
public class Board extends JFrame implements ActionListener {

	private static final long serialVersionUID = -2121862837114434361L;

	// Andrea's items
	static JButton deck;
	static JButton UNO;

	static JButton wildHand;
	static JButton redHand;
	static JButton greenHand;
	static JButton blueHand;
	static JButton yellowHand;

	static JLabel wildHandp2;
	static JLabel redHandp2;
	static JLabel greenHandp2;
	static JLabel blueHandp2;
	static JLabel yellowHandp2;

	static JLabel wildHandp3;
	static JLabel redHandp3;
	static JLabel greenHandp3;
	static JLabel blueHandp3;
	static JLabel yellowHandp3;

	static JLabel wildHandp4;
	static JLabel redHandp4;
	static JLabel greenHandp4;
	static JLabel blueHandp4;
	static JLabel yellowHandp4;

	JPanel boardPanel;

	JLabel discard;
	JLabel cards;
	JLabel p1;
	JLabel p2;
	JLabel p3;
	JLabel p4;
	JLabel playerTurn;
	
	JTable board;
	JFrame frame;

	Timer timer;

	// Kristen's items
	JPanel menuPanel;
	JMenuItem newAction;
	JMenuItem saveAction;
	JMenuItem loadAction;
	JMenuItem settingsAction;

	Color backgroundColor = Color.GREEN;
	Controller controller;
	

	/**
	 * Constructs the board frame and sets the size
	 * 
	 * @param c, the controller         
	 * @author Andrea Wakeland
	 */
	public Board(Controller c) {
		controller = c;
		frame = new JFrame("UNO");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		menuBar(frame);
		try {
			addComponentsToPane(frame);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		Insets insets = frame.getInsets();
		frame.setSize(1200 + insets.left + insets.right, 800 + insets.top
				+ insets.bottom);
		frame.setVisible(true);
		setColor();

	}

	/**
	 * This class adds all components to the board.
	 * 
	 * @param pane, where the components are added     
	 * @author Andrea Wakeland
	 */
	public void addComponentsToPane(Container pane) throws IOException {

		
		pane.setLayout(null);


		deck = new JButton(new ImageIcon(".\\images\\deck.png"));
		cards = new JLabel(new ImageIcon(".\\images\\discard.png"));
		UNO = new JButton(new ImageIcon(".\\images\\UNO.png"));

		p1 = new JLabel("Player 1");
		p2 = new JLabel("Player 2");
		p3 = new JLabel("Player 3");
		p4 = new JLabel("Player 4");
		playerTurn = new JLabel("Turn: ");

		wildHand = new JButton(new ImageIcon(".\\images\\wildHand.png"));
		redHand = new JButton(new ImageIcon(".\\images\\redHand.png"));
		blueHand = new JButton(new ImageIcon(".\\images\\blueHand.png"));
		yellowHand = new JButton(new ImageIcon(".\\images\\yellowHand.png"));
		greenHand = new JButton(new ImageIcon(".\\images\\greenHand.png"));

		wildHandp2 = new JLabel(new ImageIcon(".\\images\\wildHand.png"));
		redHandp2 = new JLabel(new ImageIcon(".\\images\\redHand.png"));
		blueHandp2 = new JLabel(new ImageIcon(".\\images\\blueHand.png"));
		yellowHandp2 = new JLabel(new ImageIcon(".\\images\\yellowHand.png"));
		greenHandp2 = new JLabel(new ImageIcon(".\\images\\greenHand.png"));

		wildHandp3 = new JLabel(new ImageIcon(".\\images\\wildHandside.png"));
		redHandp3 = new JLabel(new ImageIcon(".\\images\\redHandside.png"));
		blueHandp3 = new JLabel(new ImageIcon(".\\images\\blueHandside.png"));
		yellowHandp3 = new JLabel(
				new ImageIcon(".\\images\\yellowHandside.png"));
		greenHandp3 = new JLabel(new ImageIcon(".\\images\\greenHandside.png"));

		wildHandp4 = new JLabel(new ImageIcon(".\\images\\wildHandside.png"));
		redHandp4 = new JLabel(new ImageIcon(".\\images\\redHandside.png"));
		blueHandp4 = new JLabel(new ImageIcon(".\\images\\blueHandside.png"));
		yellowHandp4 = new JLabel(
				new ImageIcon(".\\images\\yellowHandside.png"));
		greenHandp4 = new JLabel(new ImageIcon(".\\images\\greenHandside.png"));

		pane.add(deck);
		pane.add(cards);
		pane.add(UNO);

		pane.add(p1);
		pane.add(p2);
		pane.add(p3);
		pane.add(p4);
		pane.add(playerTurn);

		pane.add(wildHand);
		pane.add(redHand);
		pane.add(blueHand);
		pane.add(yellowHand);
		pane.add(greenHand);

		pane.add(wildHandp2);
		pane.add(redHandp2);
		pane.add(blueHandp2);
		pane.add(yellowHandp2);
		pane.add(greenHandp2);

		pane.add(wildHandp3);
		pane.add(redHandp3);
		pane.add(blueHandp3);
		pane.add(yellowHandp3);
		pane.add(greenHandp3);

		pane.add(wildHandp4);
		pane.add(redHandp4);
		pane.add(blueHandp4);
		pane.add(yellowHandp4);
		pane.add(greenHandp4);

		Insets insets = pane.getInsets();

		Dimension size = deck.getPreferredSize();

		deck.setBounds(500 + insets.left, 300 + insets.top, size.width,
				size.height);
		
		size = cards.getPreferredSize();
		cards.setBounds(620 + insets.left, 300 + insets.top, size.width,
				size.height);

		size = wildHand.getPreferredSize();
		wildHand.setBounds(820 + insets.left, 640 + insets.top, size.width,
				size.height);

		size = redHand.getPreferredSize();
		redHand.setBounds(700 + insets.left, 640 + insets.top, size.width,
				size.height);

		size = blueHand.getPreferredSize();
		blueHand.setBounds(580 + insets.left, 640 + insets.top, size.width,
				size.height);

		size = yellowHand.getPreferredSize();
		yellowHand.setBounds(460 + insets.left, 640 + insets.top, size.width,
				size.height);

		size = greenHand.getPreferredSize();
		greenHand.setBounds(340 + insets.left, 640 + insets.top, size.width,
				size.height);

		deck.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				controller.drawCard();
			}
		});

		// Player's cards

		wildHand.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				HandGUI h = new HandGUI(controller, controller
						.getCurrentPlayer(), "wild");
			}
		});

			redHand.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					HandGUI h = new HandGUI(controller, controller
							.getCurrentPlayer(), "red");
				}
			});

			blueHand.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					HandGUI h = new HandGUI(controller, controller
							.getCurrentPlayer(), "blue");
				}
			});
		
			yellowHand.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					HandGUI h = new HandGUI(controller, controller
							.getCurrentPlayer(), "yellow");
				}
			});
	
			greenHand.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					HandGUI h = new HandGUI(controller, controller
							.getCurrentPlayer(), "green");
				}
			});

		//}

		// Computer card buttons, unclickable. Requires no actionListener.
		size = wildHandp2.getPreferredSize();
		wildHandp2.setBounds(340 + insets.left, 10 + insets.top, size.width,
				size.height);

		size = redHandp2.getPreferredSize();
		redHandp2.setBounds(460 + insets.left, 10 + insets.top, size.width,
				size.height);

		size = blueHandp2.getPreferredSize();
		blueHandp2.setBounds(580 + insets.left, 10 + insets.top, size.width,
				size.height);

		size = yellowHandp2.getPreferredSize();
		yellowHandp2.setBounds(700 + insets.left, 10 + insets.top, size.width,
				size.height);

		size = greenHandp2.getPreferredSize();
		greenHandp2.setBounds(820 + insets.left, 10 + insets.top, size.width,
				size.height);

		size = wildHandp3.getPreferredSize();
		wildHandp3.setBounds(10 + insets.left, 500 + insets.top, size.width,
				size.height);

		size = redHandp3.getPreferredSize();
		redHandp3.setBounds(10 + insets.left, 405 + insets.top, size.width,
				size.height);

		size = blueHandp3.getPreferredSize();
		blueHandp3.setBounds(10 + insets.left, 310 + insets.top, size.width,
				size.height);

		size = yellowHandp3.getPreferredSize();
		yellowHandp3.setBounds(10 + insets.left, 215 + insets.top, size.width,
				size.height);

		size = greenHandp3.getPreferredSize();
		greenHandp3.setBounds(10 + insets.left, 120 + insets.top, size.width,
				size.height);

		size = wildHandp4.getPreferredSize();
		wildHandp4.setBounds(1040 + insets.left, 120 + insets.top, size.width,
				size.height);

		size = redHandp4.getPreferredSize();
		redHandp4.setBounds(1040 + insets.left, 215 + insets.top, size.width,
				size.height);

		size = blueHandp4.getPreferredSize();
		blueHandp4.setBounds(1040 + insets.left, 310 + insets.top, size.width,
				size.height);

		size = yellowHandp4.getPreferredSize();
		yellowHandp4.setBounds(1040 + insets.left, 405 + insets.top,
				size.width, size.height);

		size = greenHandp4.getPreferredSize();
		greenHandp4.setBounds(1040 + insets.left, 500 + insets.top, size.width,
				size.height);

		size = p1.getPreferredSize();
		p1.setBounds(610 + insets.left, 610 + insets.top, size.width,
				size.height);

		size = p2.getPreferredSize();
		p2.setBounds(600 + insets.left, 120 + insets.top, size.width,
				size.height);

		size = p3.getPreferredSize();
		p3.setBounds(35 + insets.left, 100 + insets.top, size.width,
				size.height);

		size = p4.getPreferredSize();
		p4.setBounds(1065 + insets.left, 100 + insets.top, size.width,
				size.height);
		
		size = playerTurn.getPreferredSize();
		playerTurn.setBounds(550 + insets.left, 200 + insets.top, 100+size.width, 50+size.height);
		
		// UNO button is invisible unless a player has an UNO
		size = UNO.getPreferredSize();
		UNO.setBounds(550 + insets.left, 500 + insets.top, size.width,
				size.height);
		UNO.setVisible(false);
		
	}

	/**
	 * unoTime() in the controller calls this to find the exact time the UNO
	 * button was clicked. This method also makes the UNO button visible if
	 * there is an UNO.
	 * 
	 * @author Andrea Wakeland
	 * @return 
	 */

	public long unoTime(){
		long startTime = System.nanoTime();
		UNO.setVisible(true);
		UNO.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				buttonClicked();
			}
		});
		return System.nanoTime()-startTime;
	}

	/**
	 * Returns the time in nanoseconds
	 * 
	 * @return time in nanoseconds
	 * @author Andrea Wakeland
	 */
	public long buttonClicked() {
		long startTime = System.nanoTime();
		return System.nanoTime() - startTime;
	}

	/**
	 * This class tells the Controller that gameOn() is true once a new game starts
	 * and contains any methods that can only activate after a new game has begun.
	 * @author Andrea Wakeland
	 */
	public void game(){
		controller.gameOn(); 
		cards.setIcon(new ImageIcon(controller.seeTopCard().getImageAddress()));
		playerTurn.setText(controller.getCurrentPlayer().getName()+"'s turn");
	
		
		// Makes other players invisible if those players do not exist
				if (controller.numberOfPlayer() < 3) {
				 wildHandp3.setVisible(false);
				redHandp3.setVisible(false);
				 blueHandp3.setVisible(false);
				yellowHandp3.setVisible(false);
				 greenHandp3.setVisible(false);
				 p3.setVisible(false);
				}

				if (controller.numberOfPlayer() < 4) {
				 wildHandp4.setVisible(false);
				 redHandp4.setVisible(false);
				blueHandp4.setVisible(false);
				yellowHandp4.setVisible(false);
				 greenHandp4.setVisible(false);
				 p4.setVisible(false);
				}
	}
	
	
	/**
	 * Refreshes the discard pile, the person playing and if the player's cards are locked each turn.
	 * @author Andrea Wakeland
	 */
	public void refresh(){
		cards.setIcon(new ImageIcon(controller.seeTopCard().getImageAddress()));
		playerTurn.setText(controller.getCurrentPlayer().getName()+"'s turn");
		if(controller.getPlayer(0) != controller.getCurrentPlayer()){
			wildHand.setEnabled(false);
			 redHand.setEnabled(false);
			blueHand.setEnabled(false);
			yellowHand.setEnabled(false);
			 greenHand.setEnabled(false);
			 deck.setEnabled(false);
		}
		
	}
	
	/**
	 * Enables card menus for human player
	 * @author Andrea Wakeland
	 */
	public void startTurn(){
		wildHand.setEnabled(true);
		 redHand.setEnabled(true);
		blueHand.setEnabled(true);
		yellowHand.setEnabled(true);
		 greenHand.setEnabled(true);
		 deck.setEnabled(true);
	}
	

	/**
	 * This method creates a menu bar and places it in a container.
	 * 
	 * @param p
	 *            , The container that the menu bar will be placed in.
	 * @author Kristen
	 */
	public void menuBar(Container p) {

		menuPanel = new JPanel();

		JMenuBar menuBar = new JMenuBar();
		setJMenuBar(menuBar);

		JMenu fileMenu = new JMenu(Util.FILE);
		menuBar.add(fileMenu);

		newAction = new JMenuItem(Util.NEW_GAME);
		saveAction = new JMenuItem(Util.SAVE_GAME);
		loadAction = new JMenuItem(Util.LOAD_GAME);
		settingsAction = new JMenuItem(Util.SETTINGS);

		fileMenu.add(newAction);
		fileMenu.add(saveAction);
		fileMenu.add(loadAction);
		fileMenu.addSeparator();
		fileMenu.add(settingsAction);

		menuPanel.add(menuBar);
		getContentPane().add(menuPanel);

		newAction.addActionListener(this);
		saveAction.addActionListener(this);
		loadAction.addActionListener(this);
		settingsAction.addActionListener(this);

		menuPanel.setBackground(backgroundColor);

		p.add(menuPanel);
		Insets insets = p.getInsets();
		Dimension size = menuPanel.getPreferredSize();
		menuPanel.setBounds(0 + insets.left, 0 + insets.top, size.width,
				size.height);

	}

	/**
	 * This method recognizes when an option on the menu bar is selected. It
	 * then opens the appropriate window or filechooser based on which option
	 * was chosen.
	 * 
	 * @author Kristen
	 */
	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand() == Util.NEW_GAME) {
			NewGameGUI g = new NewGameGUI(controller);
		}
		if (e.getActionCommand() == Util.SAVE_GAME) {
			String saveToHere = fileChooser(Util.SAVE_GAME);
			controller.saveGame(saveToHere);
		}
		if (e.getActionCommand() == Util.LOAD_GAME) {
			String loadFromHere = fileChooser(Util.LOAD_GAME);
			controller.loadGame(loadFromHere);
		}
		if (e.getActionCommand() == Util.SETTINGS) {
			SettingsGUI s = new SettingsGUI(controller, this);
		}

	}

	/**
	 * This method creates a file chooser when the user wants to save or load a
	 * game.
	 * 
	 * @param s
	 *            , The title of the file chooser (either save or load)
	 * @return a String representing the location selected by the user.
	 * @author Kristen
	 */
	private String fileChooser(String s) {
		JFileChooser chooser = new JFileChooser();
		chooser.setDialogTitle(s);
		chooser.showOpenDialog(null);
		File f = chooser.getSelectedFile();
		String name = f.getName();
		String fileName = chooser.getCurrentDirectory().getAbsolutePath();
		return fileName + "\\" + name;
	}

	/**
	 * This method updates the background color and language of the game. It is
	 * called by a settings window.
	 * 
	 * @param s
	 *            , A string containing the desired language and color.
	 * @author Kristen
	 */
	public void updateBoard(String s) {

		String[] info = s.split(" ");
		String lang = info[0];
		String color = info[1];

		if (color.equals("green"))
			backgroundColor = Color.GREEN;
		if (color.equals("red"))
			backgroundColor = Color.RED;
		if (color.equals("purple"))
			backgroundColor = new Color(130, 0, 80);

		// if(lang.equals("spanish"))
		// change to spanish
		// if(lang.equals("english"))
		// change to english

		setColor();
		repaint();
	}

	/**
	 * This method changes the background color of the board It is called when
	 * the board is created and every time it is updated
	 * 
	 * @author Kristen
	 */
	private void setColor() {
		Container con = frame.getContentPane();
		con.setBackground(backgroundColor);
		menuPanel.setBackground(backgroundColor);
	}

	public static void main(String[] args) {
		Board board = new Board(new Controller());
	}

}
